package zjson

import (
	"bytes"
	"database/sql"
	"encoding/json"
)

func ToJsonNoSpaces(v interface{}) (j string, err error) {
	var b []byte
	if b, err = json.MarshalIndent(v, "", ""); err == nil {
		j = string(b)
	}
	return

}

func ToJson(v interface{}) (j string, err error) {
	var b []byte
	if b, err = json.Marshal(v); err == nil {
		j = string(b)
	}
	return
}

func ToJsonBytes(v interface{}) (j []byte, err error) {
	if j, err = json.Marshal(v); err != nil {
		j = nil
	}
	return
}

func ToObj(data string, v interface{}) (e error) {
	decoder := json.NewDecoder(bytes.NewReader([]byte(data)))
	decoder.UseNumber()
	if e = decoder.Decode(&v); e != nil {
		return
	}
	return
}

func ObjToObj(desc, source interface{}) (e error) {
	var j string
	if j, e = ToJson(source); e == nil {
		e = ToObj(j, desc)
	}
	return
}

// RowsToJson db.Row转json
func RowsToJson(rows *sql.Rows) (int, string, error) {
	var err error
	var columns []string
	if columns, err = rows.Columns(); err != nil {
		return 0, "", err
	}
	count := len(columns)
	tableData := make([]map[string]interface{}, 0)
	values := make([]interface{}, count)
	valuePtr := make([]interface{}, count)

	for rows.Next() {
		for i := 0; i < count; i++ {
			valuePtr[i] = &values[i]
		}
		if err = rows.Scan(valuePtr...); err != nil {
			return 0, "", err
		}
		entry := make(map[string]interface{})
		for i, col := range columns {
			var v interface{}
			val := values[i]
			switch t := val.(type) {
			case int8, int16, int, int32, int64, uint16, uint, uint32, uint64, float32, float64, bool, uint8:
				v = t
			case []byte:
				v = string(t)
			}
			entry[col] = v
		}
		tableData = append(tableData, entry)
	}
	var jsonData []byte
	if jsonData, err = json.Marshal(tableData); err != nil {
		return 0, "", err
	}
	strJson := string(jsonData)
	return len(tableData), strJson, err
}
